﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Input;

namespace NantAssistant.Util
{
    public enum KeyPressResult
    {
        /// <summary>
        /// Key Ignored
        /// </summary>
        None,
        /// <summary>
        /// Key Cached
        /// </summary>
        Cached,
        /// <summary>
        /// Value Ready
        /// </summary>
        Ready,
        /// <summary>
        /// Run key was pressed
        /// </summary>
        Run,
        /// <summary>
        /// Change View
        /// </summary>
        ChangeView,
        /// <summary>
        /// Toggle Selection on Highlighted
        /// </summary>
        ToggleSelect,
        /// <summary>
        /// Move Highlight Up
        /// </summary>
        MoveHighlightUp,
        /// <summary>
        /// Move Highlight Down
        /// </summary>
        MoveHighlightDown,
    }

    public class KeyPressHandler
    {
        private const int KeyPressTimeout = 5; // 5 seconds is good right?

        private int lastKeyPress;
        List<Key> cache;

        public int PressedValue { get; private set; }

        public KeyPressHandler()
        {
            cache = new List<Key>();
        }

        public KeyPressResult HandleKeyPress(Key key)
        {
            var result = KeyPressResult.None;

            if (DidKeyPressTimeout())
                cache.Clear();

            switch (key)
            {
                // also catches keypad enter
                case Key.Return:
                    if (cache.Count == 0)
                        result = KeyPressResult.Run;
                    else 
                    {
                        ParseCache();
                        result = KeyPressResult.Ready;
                    }
                    break;
                case Key.D0:
                case Key.D1:
                case Key.D2:
                case Key.D3:
                case Key.D4:
                case Key.D5:
                case Key.D6:
                case Key.D7:
                case Key.D8:
                case Key.D9:
                case Key.NumPad0:
                case Key.NumPad1:
                case Key.NumPad2:
                case Key.NumPad3:
                case Key.NumPad4:
                case Key.NumPad5:
                case Key.NumPad6:
                case Key.NumPad7:
                case Key.NumPad8:
                case Key.NumPad9:
                    cache.Add(key);
                    result = KeyPressResult.Cached;
                    break;
                case Key.Decimal:
                    ParseCache();
                    result = KeyPressResult.Ready;
                    break;
                case Key.Up:
                    result = KeyPressResult.MoveHighlightUp;
                    break;
                case Key.Down:
                    result = KeyPressResult.MoveHighlightDown;
                    break;
                case Key.Right:
                case Key.Left:
                case Key.Space:
                    result = KeyPressResult.ToggleSelect;
                    break;
                case Key.Tab:
                    result = KeyPressResult.ChangeView;
                    break;
            }

            return result;
        }

        private void ParseCache()
        {
            if (cache.Count == 0)
                return;

            // should always have the numeric value at the end
            // i.e. D0 or NumPad0
            string toParse = "";
            foreach (var key in cache)
            {
                var val = key.ToString();
                toParse += val[val.Length - 1];
            }

            cache.Clear();

            int i;
            if (!int.TryParse(toParse, out i))
                throw new InvalidCastException(string.Format("Key Press value ({0}) could not be parsed.", toParse));

            PressedValue = i;
        }

        // my hack timeout
        private bool DidKeyPressTimeout()
        {
            int current = DateTime.Now.Second;
            bool timeout = (current - lastKeyPress) > KeyPressTimeout;
            lastKeyPress = current;

            return timeout;
        }

    }
}
